package br.com.virtual.base.controller.cadastro;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

import br.com.virtual.base.controller.util.CidadeMB;
import br.com.virtual.base.controller.util.VirtualMB;
import br.com.virtual.base.enums.ActionFormEnum;
import br.com.virtual.base.enums.SessionNameEnum;
import br.com.virtual.base.enums.TipoEnderecoEnum;
import br.com.virtual.base.enums.TipoPessoaEnum;
import br.com.virtual.base.enums.TipoUsuarioEnum;
import br.com.virtual.base.exceptions.VirtualValidationException;
import br.com.virtual.cadastrar.model.Endereco;
import br.com.virtual.cadastrar.model.Pessoa;
import br.com.virtual.cadastrar.model.PessoaFisica;
import br.com.virtual.cadastrar.model.PessoaJuridica;
import br.com.virtual.cadastrar.model.Usuario;
import br.com.virtual.cadastrar.service.EnderecoService;
import br.com.virtual.cadastrar.service.PessoaFisicaService;
import br.com.virtual.cadastrar.service.PessoaJuridicaService;
import br.com.virtual.cadastrar.service.PessoaService;

@ManagedBean(name = "pessoaMB")
@ViewScoped
public class PessoaMB extends VirtualMB {

	private static final long serialVersionUID = 1L;

	private List<SelectItem> liTiposPessoa;
	private List<TipoUsuarioEnum> tipoUsuario;
	private List<Pessoa> pessoas;

	private Pessoa pessoa;
	private PessoaFisica pessoaFisica;
	private PessoaJuridica pessoaJuridica;
	private TipoPessoaEnum tipoPessoa;
	private Endereco endereco;

	private ActionFormEnum stateForm;

	private boolean flagPessoaFisica = true;

	@EJB
	private PessoaService pessoaService;
	@EJB
	private PessoaFisicaService pessoaFisicaService;
	@EJB
	private PessoaJuridicaService pessoaJuridicaService;
	@EJB
	private EnderecoService enderecoService;

	@PostConstruct
	private void init() {

		Pessoa pessoa = (Pessoa) FacesContext.getCurrentInstance()
				.getExternalContext().getFlash().get("pessoa");

		if (pessoa == null)
			novo();
		else {

			this.linkRetorno = (String) FacesContext.getCurrentInstance()
					.getExternalContext().getFlash().get("retorno");
			if (pessoa.getTipoPessoa().equals(TipoPessoaEnum.FISICA))
				this.pessoaFisica = this.pessoaFisicaService.read(pessoa
						.getId());
			else
				this.pessoaJuridica = this.pessoaJuridicaService.read(pessoa
						.getId());

			this.tipoPessoa = pessoa.getTipoPessoa();
			this.stateForm = ActionFormEnum.UPDATE;

		}

	}

	public void edit() {

		this.stateForm = ActionFormEnum.UPDATE;
		tipoPessoa = this.pessoa.getTipoPessoa();
		this.definePessoa();

	}

	public void delete() {

		this.pessoaService.delete(pessoa);
	}

	public void novo() {

		this.pessoas = null;
		tipoPessoa = TipoPessoaEnum.FISICA;
		pessoa = new Pessoa();
		pessoaFisica = new PessoaFisica();
		pessoaJuridica = new PessoaJuridica();
		endereco = new Endereco();
		endereco.setTipoEndereco(TipoEnderecoEnum.PRINCIPAL);
		// pessoaFisica.getEnderecos().add(endereco);
		stateForm = ActionFormEnum.CREATE;
	}

	/**
	 * Método utilizado para cliente registrar-se no site.
	 * 
	 * @return String que redireciona para tela de login.
	 */
	public String save() {

		try {

			if (this.stateForm.equals(ActionFormEnum.CREATE)) {
				
				if (tipoPessoa.equals(TipoPessoaEnum.FISICA)) {

					this.pessoaFisicaService.create(pessoaFisica);
					endereco.setPessoa(pessoaFisica);

				} else {
					this.pessoaJuridicaService.create(pessoaJuridica);
					endereco.setPessoa(pessoaJuridica);

				}

				endereco.setTipoEndereco(TipoEnderecoEnum.PRINCIPAL);
				if( endereco.getAlias() == null || endereco.getAlias().isEmpty())
					endereco.setAlias(TipoEnderecoEnum.PRINCIPAL.getNome());
				this.enderecoService.create(endereco);

			} else {
				if (tipoPessoa.equals(TipoPessoaEnum.FISICA))

					this.pessoaFisicaService.update(pessoaFisica);
				else
					this.pessoaJuridicaService.update(pessoaJuridica);

				this.enderecoService.update(endereco);

			}

		} catch (VirtualValidationException e) {
		}

		this.novo();

		if (isAdministrador())
			return null;
		else
			return "/autenticar/autenticar.jsf?faces-redirect=true";
	}

	public String alterarDadosPessoais() {

		try {
			String nomeCliente = "";
			if (this.pessoaFisica != null){
				this.pessoaFisicaService.update(pessoaFisica);
				nomeCliente = getNomeClienteToSession(pessoaFisica);
			}
			else{
				this.pessoaJuridicaService.update(pessoaJuridica);
				nomeCliente = getNomeClienteToSession(pessoaJuridica);
			}
			addFacesMessage("Dados pessoais atualizados com sucesso.",
					FacesMessage.SEVERITY_INFO, null);
			
			setSession(SessionNameEnum.NOME_USUARIO_EXIBIR.toString(), nomeCliente);
			
			return linkRetorno;

		} catch (VirtualValidationException v) {

		}

		return null;
	}

	public void definePessoa() {

		if (tipoPessoa.equals(TipoPessoaEnum.FISICA)) {

			if (this.stateForm.equals(ActionFormEnum.CREATE)) {

				pessoaFisica = new PessoaFisica();
				endereco = new Endereco();

			} else {

				pessoaFisica = pessoaFisicaService.read(pessoa.getId());
				endereco = getEnderecoResidencial(pessoa);
				((CidadeMB) getManagedBean("cidadeMB")).setEstado(endereco
						.getCidade().getEstado());
			}
			pessoaJuridica = null;
			flagPessoaFisica = true;

		} else {

			if (this.stateForm.equals(ActionFormEnum.CREATE)) {

				pessoaJuridica = new PessoaJuridica();
				endereco = new Endereco();
			} else {

				pessoaJuridica = pessoaJuridicaService.read(pessoa.getId());
				endereco = getEnderecoResidencial(pessoa);

				((CidadeMB) getManagedBean("cidadeMB")).setEstado(endereco
						.getCidade().getEstado());
			}

			pessoaFisica = null;
			flagPessoaFisica = false;
		}
	}

	private Endereco getEnderecoResidencial(Pessoa pessoa) {

		List<Endereco> enderecos = this.enderecoService.getList(pessoa);

		for (Endereco e : enderecos) {
			if (e.getTipoEndereco().equals(TipoEnderecoEnum.PRINCIPAL))
				return e;
		}

		return new Endereco();
	}

	private void carregaTipoPessoa() {

		liTiposPessoa = new ArrayList<SelectItem>();
		for (TipoPessoaEnum tp : TipoPessoaEnum.values())
			liTiposPessoa.add(new SelectItem(tp, tp.getNome()));

	}

	public Usuario getUsuarioPessoa() {

		if (tipoPessoa.equals(TipoPessoaEnum.FISICA))
			return this.pessoaFisica.getUsuario();
		else
			return this.pessoaJuridica.getUsuario();
	}
	
	public Long getIdPessoa(Pessoa pessoa){
		
		if( pessoa.getId() == null)
			return 0L;
		else
			return pessoa.getId();
		
	}

	/*
	 * GETTER & SETTER
	 */

	public List<SelectItem> getLiTiposPessoa() {

		if (liTiposPessoa == null)
			carregaTipoPessoa();
		return liTiposPessoa;
	}

	public void setLiTiposPessoa(List<SelectItem> liTiposPessoa) {
		this.liTiposPessoa = liTiposPessoa;
	}

	public PessoaFisica getPessoaFisica() {
		return pessoaFisica;
	}

	public void setPessoaFisica(PessoaFisica pessoaFisica) {
		this.pessoaFisica = pessoaFisica;
	}

	public PessoaJuridica getPessoaJuridica() {
		return pessoaJuridica;
	}

	public void setPessoaJuridica(PessoaJuridica pessoaJuridica) {
		this.pessoaJuridica = pessoaJuridica;
	}

	public boolean isFlagPessoaFisica() {
		return flagPessoaFisica;
	}

	public void setFlagPessoaFisica(boolean flagPessoaFisica) {
		this.flagPessoaFisica = flagPessoaFisica;
	}

	public ActionFormEnum getStateForm() {
		return stateForm;
	}

	public void setStateForm(ActionFormEnum stateForm) {
		this.stateForm = stateForm;
	}

	public TipoPessoaEnum getTipoPessoa() {
		return tipoPessoa;
	}

	public void setTipoPessoa(TipoPessoaEnum tipoPessoa) {
		this.tipoPessoa = tipoPessoa;
	}

	public Endereco getEndereco() {
		return endereco;
	}

	public void setEndereco(Endereco endereco) {
		this.endereco = endereco;
	}

	public List<TipoUsuarioEnum> getTipoUsuario() {
		if (this.tipoUsuario == null) {
			Set<TipoUsuarioEnum> tu = new TreeSet<TipoUsuarioEnum>();
			for (TipoUsuarioEnum t : TipoUsuarioEnum.values())
				tu.add(t);

			this.tipoUsuario = new ArrayList<TipoUsuarioEnum>(tu);

		}
		return tipoUsuario;
	}

	public void setTipoUsuario(List<TipoUsuarioEnum> tipoUsuario) {
		this.tipoUsuario = tipoUsuario;
	}

	public List<Pessoa> getPessoas() {
		if (this.pessoas == null)
			this.pessoas = this.pessoaService.listToShow();

		return pessoas;
	}

	public void setPessoas(List<Pessoa> pessoas) {
		this.pessoas = pessoas;
	}

	public Pessoa getPessoa() {
		return pessoa;
	}

	public void setPessoa(Pessoa pessoa) {
		this.pessoa = pessoa;
	}

}
